<template>
  <div class="api-tester">
    <!-- 请求信息区域 -->
    <div class="request-info">
      <el-tag :type="methodTagType" class="method-tag" effect="plain">{{ props.method }}</el-tag>
      <div class="url-container">
        <span class="url-label">请求地址：</span>
        <span class="url-text">{{ props.url }}</span>
      </div>
    </div>

    <!-- 请求参数区域 -->
    <div class="section">
      <div class="section-header">
        <div class="header-left">
          <span class="title">请求参数</span>
          <el-tag size="small" type="info" effect="plain">JSON</el-tag>
        </div>
        <div class="header-right">
          <el-tooltip content="格式化JSON" placement="top">
            <el-button type="primary" link @click="formatJson('request')">
              <el-icon><Refresh /></el-icon>
            </el-button>
          </el-tooltip>
        </div>
      </div>
      <div class="editor-wrapper">
        <CodeEditor
          v-model="requestParams"
          mode="application/json"
          theme="monokai"
          :height="150"
          ref="requestEditor"
        />
      </div>
    </div>

    <!-- 操作按钮 -->
    <div class="actions">
      <el-button
        type="primary"
        :loading="loading"
        :disabled="requestDisabled"
        @click="handleRequest"
        size="large"
      >
        <el-icon><Position /></el-icon>
        发送请求
      </el-button>
      <el-button @click="clearResponse" size="large">
        <el-icon><Delete /></el-icon>
        清空响应
      </el-button>
    </div>

    <!-- 响应结果区域 -->
    <div class="section response-section">
      <div class="section-header">
        <div class="header-left">
          <span class="title">返回响应</span>
          <el-tag size="small" type="info" effect="plain">JSON</el-tag>
        </div>
        <div class="status" v-if="responseStatus">
          <el-tag :type="responseStatus.type" effect="dark">{{ responseStatus.text }}</el-tag>
          <span class="time">耗时：{{ responseTime }}ms</span>
        </div>
      </div>
      <div class="editor-wrapper">
        <CodeEditor
          v-model="responseData"
          mode="application/json"
          theme="monokai"
          :height="120"
          :readOnly="true"
          ref="responseEditor"
        />
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import { ElMessage } from 'element-plus'
import { Position, Refresh, Delete } from '@element-plus/icons-vue'
import CodeEditor from '@/components/CodeEditor/index.vue'
import axios from 'axios'
import type { AxiosInstance, InternalAxiosRequestConfig } from 'axios'
import { useUserStore } from '@/stores/user'

interface Props {
  url: string // API请求地址
  method?: string // 请求方法
  initialParams?: string // 初始请求参数
}

const props = withDefaults(defineProps<Props>(), {
  method: 'POST',
  initialParams: '{}',
})

// 创建axios实例
const service: AxiosInstance = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
  timeout: 10000,
})

// 请求拦截器
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    const userStore = useUserStore()
    const token = userStore.token
    const tenantId = userStore.tenantId
    if (token && config.headers) {
      // 添加token到请求头
      config.headers['Authorization'] = `Bearer ${token}`
      // 添加租户ID
      if (tenantId) {
        config.headers['Tenant-Id'] = tenantId
      }
    }
    return config
  },
  (error) => {
    return Promise.reject(error)
  },
)

// 编辑器引用
const requestEditor = ref()
const responseEditor = ref()

// 数据
const requestParams = ref(props.initialParams)
const responseData = ref('')
const loading = ref(false)
const responseTime = ref<number>(0)
const responseStatus = ref<{ type: string; text: string } | null>(null)
const requestDisabled = ref(false) // 控制请求按钮是否禁用

// 格式化JSON
const formatJson = (type: 'request' | 'response') => {
  try {
    if (type === 'request') {
      const parsed = JSON.parse(requestParams.value)
      requestParams.value = JSON.stringify(parsed, null, 2)
      requestEditor.value?.refresh()
    } else {
      const parsed = JSON.parse(responseData.value)
      responseData.value = JSON.stringify(parsed, null, 2)
      responseEditor.value?.refresh()
    }
  } catch (error) {
    ElMessage.error('JSON格式化失败：无效的JSON格式')
  }
}
const emit = defineEmits(['success'])

// 发送请求
const handleRequest = async () => {
  try {
    // 验证JSON格式
    const params = JSON.parse(requestParams.value)

    loading.value = true
    const startTime = Date.now()

    // 发送请求
    const response = await service({
      url: props.url,
      method: props.method,
      data: params,
    })

    // 计算响应时间
    responseTime.value = Date.now() - startTime

    // 设置响应状态
    responseStatus.value = {
      type: response.status === 200 ? 'success' : 'warning',
      text: `${response.status} ${response.statusText}`,
    }

    // 格式化响应数据
    responseData.value = JSON.stringify(response.data, null, 2)
    responseEditor.value?.refresh()

    // 如果请求成功，禁用发送请求按钮
    if (response.data && response.data.code === 200) {
      requestDisabled.value = true
    }
  } catch (error: any) {
    // 处理错误
    responseStatus.value = {
      type: 'danger',
      text: error.response?.status
        ? `${error.response.status} ${error.response.statusText}`
        : '请求失败',
    }
    responseData.value = JSON.stringify(
      {
        error: error.message,
        details: error.response?.data,
      },
      null,
      2,
    )
    responseEditor.value?.refresh()
  } finally {
    loading.value = false
    // 传递响应数据给父组件
    emit('success')
  }
}

// 清空响应
const clearResponse = () => {
  responseData.value = ''
  responseStatus.value = null
  responseTime.value = 0
  requestDisabled.value = false // 重置按钮状态
  responseEditor.value?.refresh()
}

// 初始化
onMounted(() => {
  // 格式化初始参数
  if (props.initialParams) {
    formatJson('request')
  }
})

// 根据请求方法设置标签类型
const methodTagType = computed(() => {
  const methodMap: Record<string, string> = {
    GET: 'success',
    POST: 'primary',
    PUT: 'warning',
    DELETE: 'danger',
  }
  return methodMap[props.method] || 'info'
})
</script>

<style scoped>
.api-tester {
  padding: 16px;
  background-color: var(--el-bg-color);
  border-radius: 8px;
}

.request-info {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
  padding: 8px 12px;
  background-color: var(--el-fill-color-light);
  border-radius: 6px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.method-tag {
  font-weight: 600;
  min-width: 70px;
  text-align: center;
  font-size: 14px;
}

.url-container {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
}

.url-label {
  color: var(--el-text-color-secondary);
  font-size: 14px;
}

.url-text {
  color: var(--el-text-color-primary);
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size: 14px;
  word-break: break-all;
}

.section {
  margin-bottom: 16px;
  background-color: var(--el-bg-color-page);
  border-radius: 6px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}

.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 12px;
  border-bottom: 1px solid var(--el-border-color-light);
}

.header-left {
  display: flex;
  align-items: center;
  gap: 8px;
}

.title {
  font-size: 15px;
  font-weight: 500;
  color: var(--el-text-color-primary);
}

.editor-wrapper {
  padding: 12px;
}

.actions {
  display: flex;
  gap: 12px;
  margin-bottom: 16px;
  padding: 0 12px;
}

.status {
  display: flex;
  align-items: center;
  gap: 12px;
}

.time {
  font-size: 13px;
  color: var(--el-text-color-secondary);
}

.response-section {
  margin-bottom: 0;
}

:deep(.el-button--large) {
  padding: 8px 16px;
  font-weight: 500;
}

:deep(.el-icon) {
  margin-right: 4px;
}

:deep(.code-editor) {
  border: 1px solid var(--el-border-color-light);
  border-radius: 4px;
}
</style>
